package com.study.ws.config.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.study.ws.config.redis.listener.RedisListener;
import org.springframework.boot.task.ThreadPoolTaskExecutorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * @author xl-9527
 * @since 2025/3/28
 **/
@Configuration(proxyBeanMethods = false)
public class RedisCacheConfiguration {

    @Bean
    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory, Jackson2ObjectMapperBuilder objectMapperBuilder) {
        final ObjectMapper objectMapper = objectMapperBuilder.createXmlMapper(false).build();
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        final StringRedisSerializer serializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setHashKeySerializer(serializer);
        final Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);
        redisTemplate.setValueSerializer(jsonSerializer);
        redisTemplate.setHashValueSerializer(jsonSerializer);
        return redisTemplate;
    }

    @Bean
    RedisMessageListenerContainer redisMessageListenerContainer(final RedisConnectionFactory redisConnectionFactory, final MessageListenerAdapter messageListenerAdapter) {
        final RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
        listenerContainer.setConnectionFactory(redisConnectionFactory);
        final ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutorBuilder()
                .corePoolSize(2)
                .maxPoolSize(10)
                .threadNamePrefix("redis-listener-task-")
                .build();
        taskExecutor.initialize();
        listenerContainer.setTaskExecutor(taskExecutor);
        // 注册监听的频道
        listenerContainer.addMessageListener(messageListenerAdapter, new PatternTopic("test"));
        return listenerContainer;
    }

    @Bean
    MessageListenerAdapter messageListenerAdapter(final SimpMessagingTemplate simpMessagingTemplate) {
        return new MessageListenerAdapter(new RedisListener(simpMessagingTemplate));
    }
}
